Skip to content

feat: add public queue admin APIs (requeue, shutdown, resources)#405

Merged
pratyush618 merged 8 commits into
masterfrom
feat/python-public-admin-apis
Jul 11, 2026
Merged

feat: add public queue admin APIs (requeue, shutdown, resources)#405
pratyush618 merged 8 commits into
masterfrom
feat/python-public-admin-apis

Conversation

@pratyush618

@pratyush618 pratyush618 commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add public Queue APIs (requeue_job, shutdown, reload_resources, predicate_stats, analyze_arguments) replacing the internal underscore-prefixed accessors the docs had flagged as internal
  • Add a requeue_stuck core storage op to recover Running jobs that no automatic mechanism touches (hung-but-heartbeating worker, huge timeout, or a claim-less Running job)
  • Add queue.task(expires=) as a per-task default; delay()/map() now forward expires (previously never passed)
  • Flip docs pages from the internal-accessor annotations to the new public APIs

Changes

  • Rust core: requeue_stuck(id, now) in diesel_common (SQLite+Postgres, single transaction) and a Redis Lua script (SISMEMBER Running-set guard). Atomically resets a stuck Running job to Pending, deletes its execution claim, clears a stale cancel request, preserves retry budget. Contract test test_requeue_stuck runs against all 3 backends.
  • Python API: requeue_job/arequeue_job, shutdown() (programmatic graceful shutdown), reload_resources/areload_resources (programmatic hot reload; {} when no runtime active), predicate_stats() (allowed/denied/deferred/cancelled/errors), analyze_arguments() -> InterceptionReport (queue-level interception dry-run; empty when interception off). expires follows the default_timeout plumbing.
  • Docs: workers, predicates, tasks, interception, troubleshooting, configuration, and api-reference pages updated to the public APIs.

Test plan

  • cargo fmt / clippy / check (default, postgres, redis, native-async)
  • cargo test --workspace
  • Redis + Postgres contract suites verified locally against docker services
  • Python: 1124 passed, 4 skipped
  • ruff + mypy clean
  • docs typecheck / lint / check:parity / build

Summary by CodeRabbit

  • New Features

    • Added queue.requeue_job() to recover stuck running jobs, release stale claims, preserve retry budgets, and prevent duplicate cancellation.
    • Added task-level job expiry defaults with per-call overrides.
    • Added graceful queue.shutdown(), resource hot reload, argument analysis, predicate statistics, and async counterparts.
  • Documentation

    • Expanded API and troubleshooting guidance for job recovery, expiration, worker shutdown, resources, interception, and predicate metrics.
  • Tests

    • Added coverage for recovery, expiration, shutdown, resource reloads, argument analysis, and predicate statistics.

Atomically resets a stuck Running job to Pending, releases its
execution claim, and clears any stale cancel request, without
consuming retry budget. No automatic path recovers a Running job
whose worker is hung-but-heartbeating or whose claim row is gone.
Also forwards the default through delay() and map(), which never
passed expires before.
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The storage layer now supports atomically requeueing stuck running jobs. Python exposes job requeueing, task expiry defaults, resource reload and argument analysis, predicate statistics, and graceful shutdown APIs, with synchronous/asynchronous wrappers, tests, type stubs, and documentation updates.

Stuck Job Recovery

Layer / File(s) Summary
Storage requeue operation
crates/taskito-core/src/storage/...
Adds conditional Diesel and Redis transitions from Running to Pending, clearing cancel state and execution claims.
Storage contract validation
crates/taskito-core/tests/rust/storage_tests.rs
Verifies state reset, claim removal, retry preservation, and no-op behavior.
Python requeue API
crates/taskito-python/..., sdks/python/taskito/..., sdks/python/tests/core/test_requeue.py, docs/content/docs/...
Exposes synchronous and asynchronous requeue methods and documents and tests their behavior.

Python Queue API Expansion

Layer / File(s) Summary
Task expiry defaults
sdks/python/taskito/..., sdks/python/tests/core/test_expires.py, docs/content/docs/shared/guides/core/tasks.mdx
Propagates decorator-level expiry defaults through task enqueue methods, with per-call overrides.
Resource and interception APIs
sdks/python/taskito/..., sdks/python/tests/resources/..., docs/content/docs/python/api-reference/queue/resources.mdx, docs/content/docs/shared/guides/resources/...
Adds public resource reload and argument-analysis APIs with async wrappers, tests, and documentation.
Predicate statistics API
sdks/python/taskito/mixins/predicates.py, sdks/python/tests/core/test_predicates_enqueue.py, docs/content/docs/shared/guides/core/predicates.mdx
Exposes predicate outcome counters and updates their usage examples.
Public shutdown API
sdks/python/taskito/mixins/lifecycle.py, sdks/python/tests/..., docs/content/docs/...
Adds graceful queue.shutdown() and replaces internal shutdown calls in tests and guides.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Queue
  participant Storage
  participant Backend
  Queue->>Storage: requeue_job(job_id)
  Storage->>Backend: requeue_stuck(job_id, now)
  Backend->>Backend: move Running job to Pending
  Backend->>Backend: clear execution claim
  Backend-->>Storage: return boolean
  Storage-->>Queue: return result
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: new public queue admin APIs for requeue, shutdown, and resource controls.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/python-public-admin-apis

Comment @coderabbitai help to get the list of available commands.

@pratyush618 pratyush618 self-assigned this Jul 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
sdks/python/taskito/mixins/decorators.py (1)

360-366: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Move expires to the end or make the decorator keyword-only. Inserting it before priority changes every existing positional @queue.task(...) call: later arguments like priority, rate_limit, and queue will shift into expires, causing silent behavior changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdks/python/taskito/mixins/decorators.py` around lines 360 - 366, Update the
task decorator signature in task so the newly added expires parameter is placed
after all existing positional parameters, or make the decorator parameters
keyword-only; preserve the current positional ordering for priority, rate_limit,
queue, and other existing arguments.
🧹 Nitpick comments (2)
sdks/python/taskito/task.py (1)

23-34: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Same mid-signature insertion pattern as QueueDecoratorMixin.task().

default_expires is inserted before inject in a positional-or-keyword __init__. Lower risk since the only known constructor call site (decorators.py) uses kwargs, but TaskWrapper is a public type — worth applying the same fix (append at end or keyword-only) for consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdks/python/taskito/task.py` around lines 23 - 34, Update
TaskWrapper.__init__ so default_expires does not precede the existing inject
parameter in the positional-or-keyword signature; move default_expires after
inject or make it keyword-only, and update any affected calls while preserving
backward compatibility.
sdks/python/tests/core/test_expires.py (1)

1-88: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Solid coverage of the default/override/fallback logic and an end-to-end expiry check. One gap: no test exercises .map() forwarding expires (only delay/apply_async are covered), though it shares the same _default_expires field so risk is low.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdks/python/tests/core/test_expires.py` around lines 1 - 88, Add a test
covering task-level expiry propagation through the task’s `.map()` API, using a
task configured with an `expires` default, invoking `map()`, and asserting the
capture middleware receives that expiry value for the enqueued jobs. Place it
alongside the existing expiry forwarding tests and use `_queue_with_capture` and
`_CaptureEnqueue`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@sdks/python/taskito/mixins/decorators.py`:
- Around line 360-366: Update the task decorator signature in task so the newly
added expires parameter is placed after all existing positional parameters, or
make the decorator parameters keyword-only; preserve the current positional
ordering for priority, rate_limit, queue, and other existing arguments.

---

Nitpick comments:
In `@sdks/python/taskito/task.py`:
- Around line 23-34: Update TaskWrapper.__init__ so default_expires does not
precede the existing inject parameter in the positional-or-keyword signature;
move default_expires after inject or make it keyword-only, and update any
affected calls while preserving backward compatibility.

In `@sdks/python/tests/core/test_expires.py`:
- Around line 1-88: Add a test covering task-level expiry propagation through
the task’s `.map()` API, using a task configured with an `expires` default,
invoking `map()`, and asserting the capture middleware receives that expiry
value for the enqueued jobs. Place it alongside the existing expiry forwarding
tests and use `_queue_with_capture` and `_CaptureEnqueue`.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c4cefe76-6026-4071-b4a8-6c1b58c8abb5

📥 Commits

Reviewing files that changed from the base of the PR and between 77938fa and a4205b0.

📒 Files selected for processing (31)
  • crates/taskito-core/src/storage/diesel_common/jobs.rs
  • crates/taskito-core/src/storage/mod.rs
  • crates/taskito-core/src/storage/redis_backend/jobs/state.rs
  • crates/taskito-core/src/storage/traits.rs
  • crates/taskito-core/tests/rust/storage_tests.rs
  • crates/taskito-python/src/py_queue/inspection.rs
  • docs/content/docs/python/api-reference/queue/index.mdx
  • docs/content/docs/python/api-reference/queue/queues.mdx
  • docs/content/docs/python/api-reference/queue/resources.mdx
  • docs/content/docs/python/api-reference/queue/workers.mdx
  • docs/content/docs/python/guides/resources/configuration.mdx
  • docs/content/docs/shared/guides/core/predicates.mdx
  • docs/content/docs/shared/guides/core/tasks.mdx
  • docs/content/docs/shared/guides/core/workers.mdx
  • docs/content/docs/shared/guides/operations/troubleshooting.mdx
  • docs/content/docs/shared/guides/resources/interception.mdx
  • sdks/python/taskito/_taskito.pyi
  • sdks/python/taskito/async_support/mixins.py
  • sdks/python/taskito/mixins/decorators.py
  • sdks/python/taskito/mixins/lifecycle.py
  • sdks/python/taskito/mixins/operations.py
  • sdks/python/taskito/mixins/predicates.py
  • sdks/python/taskito/mixins/resources.py
  • sdks/python/taskito/task.py
  • sdks/python/tests/conftest.py
  • sdks/python/tests/core/test_expires.py
  • sdks/python/tests/core/test_predicates_enqueue.py
  • sdks/python/tests/core/test_requeue.py
  • sdks/python/tests/core/test_shutdown.py
  • sdks/python/tests/resources/test_interception.py
  • sdks/python/tests/resources/test_resources.py

@pratyush618
pratyush618 merged commit f0ac625 into master Jul 11, 2026
38 checks passed
@pratyush618
pratyush618 deleted the feat/python-public-admin-apis branch July 11, 2026 04:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant